
<template>
  <div 
  ref="terminalRef" 
  class="terminal" 
  :class="{ 'fullscreen': isFullscreen }"
  @wheel.stop 
  >
  </div>
</template>
 
<script setup>
import { Terminal } from '@xterm/xterm';
import '@xterm/xterm/css/xterm.css';
import { FitAddon } from '@xterm/addon-fit';
import { io } from 'socket.io-client';
import { useEventListener } from '@vueuse/core';
// 定义常量
const CHAR_WIDTH = 14;
const CHAR_HEIGHT = 19;
const TERMINAL_CONFIG = {
  disableStdin: false,
  fontSize: 16,
  fontFamily: 'Consolas, "Courier New", monospace',
  fontWeight: 'normal',
  fontWeightBold: 'bold',
  letterSpacing: 0,
  lineHeight: 1.0,
  scrollback: 1000,
  scrollSensitivity: 1,
  fastScrollModifier: 'Shift',
  fastScrollSensitivity: 5,
  logLevel: 'info',
  allowTransparency: true,
  theme: {
    cursor: '#ffffff',
    cursorAccent: '#000000', 
    foreground: '#ffffff',
    background: '#1e1e1e',
    selection: '#ffffff40',
  },
  convertEol: true,
  cursorBlink: true,
  cursorStyle: 'block',
  cursorWidth: 1,
  altClickMovesCursor: true,
  rightClickSelectsWord: true,
  windowsMode: true,
};

const isFullscreen = defineModel('isFullscreen', {
  type: Boolean,
  required: false,
  default: false
});

const terminalRef = ref(null);
const terminal = new Terminal(TERMINAL_CONFIG);
const fitAddon = new FitAddon();
terminal.loadAddon(fitAddon);

// 连接状态管理
let clientId = null;
let inputBuffer = '';
let sshInfo;
let socket;
let dataListener = null;

// Socket 事件处理
const handleSocketEvents = (socket) => {
  const events = {
    connect: () => {
      console.log('connect：Socket 链接成功');
      terminal.writeln('connect：Socket 链接成功');
      socket.emit('startTerminalSession', sshInfo);
    },
    disconnect: () => {
      console.log('disconnect：Socket 断开连接. 请检查您的连接.');
      terminal.writeln('disconnect：Socket 断开连接. 请检查您的连接.');
    },
    terminalSessionStarted: (data) => {
      console.log('terminalSessionStarted：' + data.message);
      terminal.writeln('terminalSessionStarted：' + data.message);
      clientId = data.clientId;
      nextTick(() => terminal.scrollToBottom());
    },
    terminalSessionError: (error) => {
      console.error('terminalSessionError：连接到主机失败:', error);
      terminal.writeln('terminalSessionError：连接到主机失败:' + error);
    },
    terminalDisconnected: (message) => {
      console.log('terminalDisconnected：' + message);
      terminal.writeln('terminalDisconnected：' + message);
    },
    terminalData: (data) => terminal.write(data)
  };

  Object.entries(events).forEach(([event, handler]) => {
    socket.on(event, handler);
  });
};

// 初始化Socket连接
function initSocket(sshInfoParam) {
  sshInfo = sshInfoParam;
  socket = io(`http://192.168.5.74:8113/control`, {
    autoConnect: false
  });
  
  socket.connect();
  handleSocketEvents(socket);
  
  if (dataListener) {
    terminal.off('data', dataListener);
  }
  
  dataListener = handleTerminalData;
  terminal.onData(dataListener);
}

// 处理终端数据
function handleTerminalData(data) {
  if (socket.connected && clientId) {
    socket.emit('input', { clientId, input: data });
  } else {
    console.error('Socket 未连接.');
    terminal.writeln('Socket 未连接.');
  }
  if (data === '\r') {
    if (inputBuffer.trim() === 'clear') {
      terminal.clear();
    }
    inputBuffer = '';
  } else {
    inputBuffer += data;
  }
}

// ESC键处理
const handleEscape = (event) => {
  if (event.key === 'Escape' && isFullscreen.value) {
    isFullscreen.value = false;
    nextTick(() => terminal.scrollToBottom());
  }
};

// 终端大小调整
function resizeTerminal() {
  if (!terminal || !fitAddon || !terminalRef.value) return;
  fitAddon.fit();
  const { offsetWidth: containerWidth, offsetHeight: containerHeight } = terminalRef.value;
  const cols = Math.floor(containerWidth / CHAR_WIDTH);
  const rows = Math.floor(containerHeight / CHAR_HEIGHT);
  terminal.resize(cols, rows);
  setTimeout(() => {
    fitAddon.fit();
    terminal.scrollToBottom();
  }, 0);
}

// 组件生命周期
onMounted(() => {
  terminal.open(terminalRef.value);
  const terminalElement = terminalRef.value;
  terminalElement.addEventListener('wheel', (e) => {
    e.stopPropagation();
    e.preventDefault();
  }, { passive: false });
  terminal.onKey(({ domEvent }) => {
    if (domEvent.key === 'Escape' && isFullscreen.value) {
      isFullscreen.value = false;
      setTimeout(resizeTerminal, 300);
      domEvent.preventDefault();
    }
  });
  document.addEventListener('keydown', handleEscape);
  nextTick(resizeTerminal);
});

// 断开连接
function disconnectTerminal() {
  socket?.emit('disconnectTerminal', clientId);
  terminal.clear();
  if (dataListener) {
    terminal.off('data', dataListener);
    dataListener = null;
  }
}

// 全屏切换
function toggleFullscreen() {
  isFullscreen.value = !isFullscreen.value;
  setTimeout(resizeTerminal, 300);
}

// 事件监听
useEventListener(window, 'beforeunload', (event) => {
  disconnectTerminal();
  terminal?.dispose();
  event.preventDefault();
  event.returnValue = '';
});

useEventListener(window, 'resize', resizeTerminal);

// 导出方法
defineExpose({
  initSocket,
  disconnectTerminal,
  resizeTerminal,
  toggleFullscreen
});
</script>
 
<style scoped lang="scss">
.terminal {
  width: 100%;
  height: 300px;
  overflow: hidden;
  transition: all 0.3s ease;
  &.fullscreen {
    position: fixed;
    top: 0;
    left: 0;
    right: 0; // 添加右边界
    bottom: 0; // 添加底部边界
    width: 100vw;
    height: 100vh;
    margin: 0;
    padding: 0;
    z-index: 1000;
    background: #1e1e1e; // 添加背景色，与终端背景色匹配
  }
  :deep(.xterm) {
    height: 100%;
    
    .xterm-screen {
      position: relative;
      // 移除 !important 标志和 height: auto
      // height: auto !important;
    }
    
    .xterm-viewport {
      position: absolute;
      overflow-y: scroll; // 从 auto 改为 scroll
      width: 100% !important; // 添加宽度以确保正确尺寸
      height: 100% !important; // 添加高度以确保正确尺寸
      // 移除隐藏滚动条的样式，允许默认滚动
      /*
      scrollbar-width: none !important;
      -ms-overflow-style: none !important;
      &::-webkit-scrollbar {
        display: none !important;
      }
      */
      &:hover {
        isolation: isolate;  // 创建新的层叠上下文
      }
    }
  }
  
}

.terminal ::-webkit-scrollbar {
  width: 8PX; /* 滚动条宽度 */
  height: 8PX; /* 横向滚动条高度 */
}

.terminal ::-webkit-scrollbar-thumb {
  background-color: #f1f1f1; /* 滚动条颜色，亮蓝色 */
  border-radius: 4px; /* 滚动条圆角 */
}

.terminal ::-webkit-scrollbar-thumb:hover {
  background-color: #125ea1; /* 悬停时滚动条颜色，加深的蓝色 */
}

.terminal ::-webkit-scrollbar-track {
  background: #1976D2; /* 滚动条背景颜色，浅灰色 */
}
</style>
